#include "TreadMillCommandUtil.h"
#include "TreadMillConstants.h"
#include "Treadmill.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <nlohmann/json.hpp>
#include <android/log.h>  // 添加 Android 日志头文件

//#define LOG_TAG "WORKOUT_DATA_HANDLER"
#define LOG_TAG "TreadMill"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)

// 定义静态变量
unsigned char TreadMillCommandUtil::header = 0;
unsigned char TreadMillCommandUtil::dataType = 0;
std::vector<unsigned char> TreadMillCommandUtil::data;
unsigned char TreadMillCommandUtil::checkSum = 0;

// 获取单例实例
Treadmill& treadmill = Treadmill::getInstance();

std::string TreadMillCommandUtil::commandType = "";

nlohmann::json jsonMsg;

std::string TreadMillCommandUtil::parseCommand(const std::string &command) {
    // 检查命令的长度
    if (command.size() < 4) {  // 根据协议调整大小
        LOGE("Command size is too small: %zu", command.size());
        return ""; // 返回空字符串，表示解析失败
    }

    // 将十六进制字符串转换为字节数组
    std::vector<unsigned char> bytes = hexStringToByteArray(command);
    header = bytes[0];
    dataType = bytes[1];
    data.assign(bytes.begin() + 2, bytes.end() - 1); // 除去校验和
    checkSum = bytes[bytes.size() - 1];

    commandType = command.substr(2, 2);
    LOGE("%s", commandType.c_str());

    // 校验和验证
    unsigned char calculatedChecksum = calculateChecksum(dataType, data);
    if (calculatedChecksum != checkSum) {
        LOGE("Checksum mismatch! Calculated: %02X, Received: %02X", calculatedChecksum, checkSum);
    }

    // 输出调试日志
    LOGI("Parsed command: header=0x%02X, dataType=0x%02X, checkSum=0x%02X", header, dataType,
         checkSum);

    std::string result = processOperatorCommand(commandType);
    return result;
}

std::vector<unsigned char> TreadMillCommandUtil::hexStringToByteArray(const std::string &s) {
    std::vector<unsigned char> data(s.length() / 2);
    for (size_t i = 0; i < s.length(); i += 2) {
        data[i / 2] = (unsigned char) ((std::stoi(s.substr(i, 1), nullptr, 16) << 4)
                                       + std::stoi(s.substr(i + 1, 1), nullptr, 16));
    }
    return data;
}

unsigned char TreadMillCommandUtil::calculateChecksum(unsigned char dataType,
                                                      const std::vector<unsigned char> &data) {
    int sum = dataType; // 开始加上 dataType
    for (unsigned char b : data) {
        sum += b; // 累加所有数据字节
    }
    return static_cast<unsigned char>(sum & 0xFF); // 对 256 取模
}

std::string TreadMillCommandUtil::processOperatorCommand(const std::string &operatorCommand) {
    if (operatorCommand == TreadMillConstants::APP_INIT) {
        return handleAppInit();
    } else if (operatorCommand == TreadMillConstants::APP_SETTING) {
        return handleAppSetting();
    } else if (operatorCommand == TreadMillConstants::APP_RESET) {
        return handleAppReset();
    } else if (operatorCommand == TreadMillConstants::APP_SET_INCLINE) {
        return handleSetIncline();
    } else if (operatorCommand == TreadMillConstants::APP_CALIBRATE) {
        return handleCalibrate();
    } else if (operatorCommand == TreadMillConstants::APP_DIAGNOSITICS) {
        return handleDiagnostics();
    } else if (operatorCommand == TreadMillConstants::APP_WORKOUT_DATA) {
        return handleWorkoutData();
    } else if (operatorCommand == TreadMillConstants::APP_STATE_CHANGED) {
        return handleStateChanged();
    } else if (operatorCommand == TreadMillConstants::APP_ERROR) {
        return handleError();
    } else {
        jsonMsg["message"] = "Unknown Command";
        return jsonMsg.dump();
    }
}

// 各个 dataType 对应的处理函数 (仅示例，处理逻辑需要根据实际需求实现)
std::string TreadMillCommandUtil::handleAppInit() {
    LOGI("Handling APP_INIT command");
    int UCBState = data[0];
    int MachineType = data[1];
    int HardwareVersion = data[2];
    int FirmwareVersion = data[3];

    treadmill.setState(UCBState);
    LOGI("%s", treadmill.getStateString().c_str());

    if (MachineType == 1) {
        LOGI("Machine type: TreadMill");
    }

    // 使用 nlohmann/json 库将数据转换为 JSON 对象
    nlohmann::json jsonData;
    jsonData["state"] = UCBState;
    jsonData["MachineType"] = MachineType;
    jsonData["HardwareVersion"] = HardwareVersion;
    jsonData["FirmwareVersion"] = FirmwareVersion;

    // 将 JSON 数据转换为字符串并输出
    return jsonData.dump();
}

std::string TreadMillCommandUtil::handleAppSetting() {
    LOGI("Handling APP_SETTING command");
    jsonMsg["message"] = std::string("Treadmill Setting ") + (checkDataACK() ? "Success" : "Failed");
    return jsonMsg.dump();
}

std::string TreadMillCommandUtil::handleAppReset() {
    LOGI("Handling APP_RESET command");
    jsonMsg["message"] = std::string("Treadmill RESET ") + (checkDataACK() ? "Success" : "Failed");
    return jsonMsg.dump();
}

std::string TreadMillCommandUtil::handleSetIncline() {
    LOGI("Handling APP_SET_INCLINE command");
    jsonMsg["message"] = std::string("Treadmill Set Incline ") + (checkDataACK() ? "Success" : "Failed");
    jsonMsg["incline"] = treadmill.getIncline();
    return jsonMsg.dump();
}

std::string TreadMillCommandUtil::handleCalibrate() {
    LOGI("Handling APP_CALIBRATE command");
    int progress = data[0];
    treadmill.setCalibrationProgress(progress);
    LOGI("Calibration Progress: %s", treadmill.getCalibrationProgress().c_str());

    nlohmann::json calibrateDataJson;
    calibrateDataJson["progress"] = progress;
    return calibrateDataJson.dump();
}

std::string TreadMillCommandUtil::handleDiagnostics() {
    LOGI("Handling APP_DIAGNOSTICS command");

    int option = treadmill.getDiagnosticsOption();
    int progress = data[0];
    int testData = data[1];

    nlohmann::json diagnosticsDataJson;
    diagnosticsDataJson["option"] = option;
    diagnosticsDataJson["progress"] = progress;
    diagnosticsDataJson["testData"] = testData;

    return diagnosticsDataJson.dump();
}

std::string TreadMillCommandUtil::handleWorkoutData() {
    LOGI("Handling APP_WORKOUT_DATA command");

    treadmill.setState(data[0]);
    treadmill.setSpeed(data[1] * 0.1f);
    treadmill.setIncline(data[2] * 1.0f);
    treadmill.setIsPerson(data[3]);

    // 打印 treadmill 的四个属性
    LOGI("Treadmill State: %s", treadmill.getStateString().c_str());
    LOGI("Current Speed: %.1f %s", treadmill.getSpeed(), treadmill.getSpeedUnit().c_str());
    LOGI("Incline: %.1f%%", treadmill.getIncline());
    LOGI("Is Person Detected: %s", treadmill.getIsPersonString().c_str());

    nlohmann::json workoutDataJson;
    workoutDataJson["state"] = treadmill.getState();
    workoutDataJson["speed"] = treadmill.getSpeed();
    workoutDataJson["speedUnit"] = treadmill.getSpeedUnit();
    workoutDataJson["incline"] = treadmill.getIncline();
    workoutDataJson["isPersonDetected"] = treadmill.getIsPerson();
    // 将 JSON 对象转化为字符串
    std::string jsonString = workoutDataJson.dump();

    return jsonString;
}

std::string TreadMillCommandUtil::handleStateChanged() {
    // 处理 APP_STATE_CHANGED 的逻辑
    LOGI("Handling APP_STATE_CHANGED command");
    int state = data[0];
    treadmill.setState(state);
    nlohmann::json stateJson;
    stateJson["state"] = state;
    return stateJson.dump();
}

std::string TreadMillCommandUtil::handleError() {
    // 处理 APP_ERROR 的逻辑
    LOGI("Handling APP_ERROR command");

    int UCBState = data[0];
    int ErrorCode = data[1];
    float SpeedAtError = data[2] * 1.0f;
    int SensorValueAtError = data[3];

    LOGI("UCB State: %d", UCBState);
    LOGI("Error Code: %d", ErrorCode);
    LOGI("Speed At Error: %.1f", SpeedAtError);
    LOGI("Sensor Value At Error: %d", SensorValueAtError);

    nlohmann::json errorDataJson;
    errorDataJson["state"] = UCBState;
    errorDataJson["code"] = ErrorCode;
    errorDataJson["speed"] = SpeedAtError;
    errorDataJson["sensorValue"] = SensorValueAtError;

    return errorDataJson.dump();
}

bool TreadMillCommandUtil::checkDataACK() {
    for (int i = 0; i < 4; i++) {
        if (data[i] != 0) {
            return false;
        }
    }
    return true;
}

// ====================== 构建命令 =====================

// 将整数转换为一个两位的十六进制字符串
std::string ComputeIntToHex(int value) {
    // 将值限制在 0-255 之间
    uint8_t byteData = static_cast<uint8_t>(value);
    std::ostringstream oss;
    oss << std::uppercase << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(byteData);
    return oss.str();
}

// 将十六进制字符串的每两个字符转为整数，并累加结果
int ComputeHexCheckSumToInt(const std::string& hexString) {
    int length = hexString.length();
    int sum = 0;

    for (int i = 0; i < length; i += 2) {
        // Extract a two-character substring and convert it to an integer
        std::string hexByte = hexString.substr(i, 2);
        sum += std::stoi(hexByte, nullptr, 16);
    }
    return sum;
}

// 将结果转换为一个两位的十六进制字符串
std::string ComputeHexCheckSumToString(const std::string& hexString) {
    int sum = ComputeHexCheckSumToInt(hexString);
    unsigned char byteData = static_cast<unsigned char>(sum);

    // Convert byte to hex string (with uppercase format and leading zeros)
    std::stringstream ss;
    ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (int)byteData;

    return ss.str();
}

std::string TreadMillCommandUtil::BuildCommandStringData(const std::string& header, const std::string& dataType, const std::string& data) {
    std::string dataHex = !data.empty() ? data : "";
    std::string checkSum = ComputeHexCheckSumToString(dataType + dataHex);

    // 格式化命令字符串
    std::stringstream commandStream;
    commandStream << header << dataType << dataHex << checkSum;

    return commandStream.str();
}

std::string TreadMillCommandUtil::InitCommand() {
    return BuildCommandStringData(TreadMillConstants::APP_HEADER, TreadMillConstants::APP_INIT, "00");
}

std::string TreadMillCommandUtil::SettingCommand(int set) {
    treadmill.setSpeedUnit(set);
    return BuildCommandStringData(TreadMillConstants::APP_HEADER, TreadMillConstants::APP_SETTING, ComputeIntToHex(set));
}

std::string TreadMillCommandUtil::ResetCommand() {
    return BuildCommandStringData(TreadMillConstants::APP_HEADER, TreadMillConstants::APP_RESET, "00");
}

std::string TreadMillCommandUtil::SetInclineCommand(float incline){
    float MidIncline = incline * 10;
    if((int)MidIncline == 200){
        LOGI("Disable incline keys on keypad");
    } else if(MidIncline < 0 || MidIncline > 120){
        LOGI("The incline must be between 0 and 120");
        MidIncline = treadmill.getIncline();
    }
    treadmill.setIncline(MidIncline);
    return BuildCommandStringData(TreadMillConstants::APP_HEADER, TreadMillConstants::APP_SET_INCLINE, ComputeIntToHex((int)MidIncline));
}

std::string TreadMillCommandUtil::CalibrateCommand() {
    return BuildCommandStringData(TreadMillConstants::APP_HEADER, TreadMillConstants::APP_CALIBRATE, "00");
}

std::string TreadMillCommandUtil::DiagnosticsCommand(int option){
    return BuildCommandStringData(TreadMillConstants::APP_HEADER, TreadMillConstants::APP_DIAGNOSITICS, ComputeIntToHex(option));
}

std::string TreadMillCommandUtil::StateChangedCommand(){
    return BuildCommandStringData(TreadMillConstants::APP_HEADER, TreadMillConstants::APP_STATE_CHANGED, "00");
}

std::string TreadMillCommandUtil::ErrorDataCommand(){
    return BuildCommandStringData(TreadMillConstants::APP_HEADER, TreadMillConstants::APP_ERROR, "00");
}


int TreadMillCommandUtil::getTreadmillState() {
    return treadmill.getState();
}